﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MaxStudio.Concrete.DBUtility
{
    
    public class LogHelper
    {
        public static String getPropertiesAndValuesOfClass(Object obj) {
            StringBuilder sb = new StringBuilder();
            Type type = obj.GetType();
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (PropertyInfo vPropertyInfos in propertyInfos)
            {
                Object propertyValue = vPropertyInfos.GetValue(obj, null);
                if (propertyValue == null)
                    sb.Append(vPropertyInfos.Name + ":null; ");
                else
                {
                    if (!vPropertyInfos.PropertyType.BaseType.Name.Equals("Object"))
                        sb.Append(vPropertyInfos.Name + ":" + propertyValue.ToString() + ";");
                }
            }
            return sb.ToString();
        }

        public static String getDifferenceOfPropertyValues(Object sourceObj, Object obj)
        {
            if (obj == null)
                throw new Exception("Invoke Error, obj could not be null");
            Type type = obj.GetType();
            // handle new object
            if (sourceObj == null)
            {
                return "Add new object:" + type.Name + ", " + getPropertiesAndValuesOfClass(obj);
            }

            Type sourceType = sourceObj.GetType();
            
            if (!sourceType.Equals(type))
                throw new Exception("Invoke Error, sourceObj and obj should be the same type");
            StringBuilder sb = new StringBuilder();
            //sb.Append("Modify object" + type.Name + ": ");
            // handle modify object
            PropertyInfo[] sourcePropertyInfos = sourceType.GetProperties();
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (PropertyInfo vSourcePropertyInfos in sourcePropertyInfos)
            {
                // only compare valuetype
                if (!(vSourcePropertyInfos.PropertyType.BaseType.Name.Equals("ValueType") 
                    || vSourcePropertyInfos.PropertyType.FullName.Equals("System.String")))
                    continue;

                for (int i = 0; i < propertyInfos.Length; i++)
                {
                    PropertyInfo vPropertyInfos = propertyInfos[i];
                    if (vSourcePropertyInfos.Name.Equals(vPropertyInfos.Name)) {
                        Object sourcePropertyValue = vSourcePropertyInfos.GetValue(sourceObj, null);
                        Object propertyValue = vPropertyInfos.GetValue(obj, null);
                        if (sourcePropertyValue == null && propertyValue == null)
                            break;
                        if (sourcePropertyValue == null && propertyValue != null)
                        {
                            sb.Append(vSourcePropertyInfos.Name + ": before is null " +
                                "'; after is '" + propertyValue.ToString() + "'; ");
                            break;
                        }
                        if (sourcePropertyValue != null && propertyValue == null)
                        {
                            sb.Append(vSourcePropertyInfos.Name + ": before is '" +
                                sourcePropertyValue.ToString() + "'; after is null; ");
                            break;
                        }

                        if (!sourcePropertyValue.Equals(propertyValue))
                        {
                            sb.Append(vSourcePropertyInfos.Name + ": before is '" +
                                sourcePropertyValue.ToString() + "'; after is '" + propertyValue.ToString() + "'; ");
                            break;
                        }
                        break;
                    }

                }
            }
            if (sb.Length == 0)
                sb.Append("Modify object " + type.Name + ": No attribute is modified ");
            else
                sb.Insert(0, "Modify object " + type.Name + ": ");
            return sb.ToString();
        }
            
    }
}
